package consumer

import (
	"cppcloud"
	"fmt"
)

// 线程安全有待加强

type tcpClientConsumer struct {
	*cppcloud.TCPClient // skipWhoami=true
}

type ConsumerManage struct {
	clis       map[string]*tcpClientConsumer
	svrlistMgr *SvrListMgr // 服务提供者管理器
	cloudapp   *cppcloud.CloudApp
}

type FeedBackHelper struct {
	svrKey string
	// result   int8
	cloudapp *cppcloud.CloudApp
}

func (fbh *FeedBackHelper) SetResult(isOk bool) {
	fbh.cloudapp.SvrStatInstance().AddInvkCount(fbh.svrKey, isOk, 1)
}

func CreateConsumerManage(capp *cppcloud.CloudApp, regList ...string) (conMgr *ConsumerManage) {
	conMgr = &ConsumerManage{clis: make(map[string]*tcpClientConsumer)}
	conMgr.cloudapp = capp
	conMgr.svrlistMgr = CreateSvrListMgr(capp, regList...)

	if nil == conMgr.svrlistMgr {
		return nil
	}
	return
}

// 消费TCP服务
func (conMgr *ConsumerManage) RequestTCP(svrname string, cmdid uint16, msg interface{}) (
	ret string, helper *FeedBackHelper, err error) {

	prvdItem := conMgr.getProviderItem(svrname)
	if nil == prvdItem {
		ret = ""
		err = &RunError{"getProviderItem| msg=no provider " + svrname}
		return
	}

	cliConsumer, exist := conMgr.clis[prvdItem.conKey]
	if !exist || nil == cliConsumer {
		if prvdItem.protocol != 1 {
			err = &RunError{"protocol not match"}
			return
		}
		attrMap := map[string]interface{}{"skipWhoami": true}
		tclient := cppcloud.MakeTCPClient(prvdItem.hostp, attrMap, 3)
		if nil == tclient {
			err = &RunError{"connect to " + prvdItem.hostp + " fail"}
			return
		}
		cliConsumer = &tcpClientConsumer{tclient}
		conMgr.clis[prvdItem.conKey] = cliConsumer
		cliConsumer.Start() // 启动接收/发送协程
	}

	helper = &FeedBackHelper{svrKey: prvdItem.conKey, cloudapp: conMgr.cloudapp}
	ret, rspCode := cliConsumer.Request(cmdid, msg)
	if 0 != rspCode {
		err = &RunError{"Request return " + fmt.Sprint(rspCode)}
	}

	return
}

func (conMgr *ConsumerManage) getProviderItem(svrname string) (svrItem *svrInfo_t) {
	svrItem = conMgr.svrlistMgr.GetSvrItem(svrname)
	if nil == svrItem {
		svrItem = conMgr.svrlistMgr.CheckConsumer(svrname)
		if nil == svrItem {
			//err = &RunError{"No provider named " + svrname + " exist"}
		}
	}
	return
}
